#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
UI组件模块
"""

import streamlit as st
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from typing import Dict, Any, List, Optional
import numpy as np

class UIComponents:
    """UI组件类"""
    
    def __init__(self):
        self.setup_matplotlib()
    
    def setup_matplotlib(self):
        """设置matplotlib中文字体"""
        try:
            plt.rcParams['font.sans-serif'] = ['SimHei', 'Arial Unicode MS', 'DejaVu Sans']
            plt.rcParams['axes.unicode_minus'] = False
        except Exception as e:
            st.warning(f"字体设置失败: {str(e)}")
    
    def display_metric_cards(self, metrics: Dict[str, Any], columns: int = 4):
        """
        显示指标卡片
        
        Args:
            metrics: 指标字典
            columns: 列数
        """
        cols = st.columns(columns)
        
        for i, (key, value) in enumerate(metrics.items()):
            with cols[i % columns]:
                if isinstance(value, (int, float)):
                    st.metric(key, f"{value:,.0f}")
                else:
                    st.metric(key, str(value))
    
    def display_data_table(
        self, 
        data: pd.DataFrame, 
        title: str = "数据表格",
        show_download: bool = True,
        download_filename: str = "data.csv"
    ):
        """
        显示数据表格
        
        Args:
            data: 数据框
            title: 标题
            show_download: 是否显示下载按钮
            download_filename: 下载文件名
        """
        st.subheader(title)
        
        if data.empty:
            st.info("暂无数据")
            return
        
        # 显示数据表格
        st.dataframe(data, use_container_width=True)
        
        # 显示统计信息
        col1, col2, col3 = st.columns(3)
        with col1:
            st.metric("总行数", len(data))
        with col2:
            st.metric("总列数", len(data.columns))
        with col3:
            st.metric("内存使用", f"{data.memory_usage(deep=True).sum() / 1024 / 1024:.2f} MB")
        
        # 下载按钮
        if show_download:
            # 统一改为Excel下载，支持中文
            import io
            with io.BytesIO() as output:
                with pd.ExcelWriter(output, engine='openpyxl') as writer:
                    data.to_excel(writer, sheet_name='数据', index=False)
                excel_bytes = output.getvalue()
            st.download_button(
                label=f"下载 {title}",
                data=excel_bytes,
                file_name=(download_filename.rsplit('.', 1)[0] + '.xlsx') if '.' in download_filename else (download_filename + '.xlsx'),
                mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
            )
    
    def display_price_comparison_chart(
        self, 
        data: pd.DataFrame, 
        title: str = "价格对比图"
    ):
        """
        显示价格对比图表
        
        Args:
            data: 包含价格数据的DataFrame
            title: 图表标题
        """
        try:
            st.subheader(title)
            
            # 检查必要的列
            required_cols = ['product_level_name', 'finalprice']
            if not all(col in data.columns for col in required_cols):
                st.warning("数据缺少必要的列用于绘制价格对比图")
                return
            
            # 按等级分组计算平均价格
            level_prices = data.groupby('product_level_name')['finalprice'].mean().sort_values(ascending=False)
            
            # 创建图表
            fig, ax = plt.subplots(figsize=(12, 6))
            
            # 绘制柱状图
            bars = ax.bar(range(len(level_prices)), level_prices.values, 
                         color=plt.cm.viridis(np.linspace(0, 1, len(level_prices))))
            
            # 设置标签
            ax.set_xlabel('产品等级')
            ax.set_ylabel('平均价格 (¥)')
            ax.set_title(title)
            ax.set_xticks(range(len(level_prices)))
            ax.set_xticklabels(level_prices.index, rotation=45)
            
            # 添加数值标签
            for i, (bar, value) in enumerate(zip(bars, level_prices.values)):
                ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 50,
                       f'¥{value:,.0f}', ha='center', va='bottom')
            
            plt.tight_layout()
            st.pyplot(fig)
            
        except Exception as e:
            st.error(f"绘制价格对比图失败: {str(e)}")
    
    def display_competitiveness_analysis(
        self, 
        data: pd.DataFrame, 
        title: str = "竞争力分析"
    ):
        """
        显示竞争力分析图表
        
        Args:
            data: 包含竞争力数据的DataFrame
            title: 图表标题
        """
        try:
            st.subheader(title)
            
            # 检查是否有竞争力相关列
            compete_cols = [col for col in data.columns if 'compete' in col.lower() or 'competitive' in col.lower()]
            
            if not compete_cols:
                st.info("数据中未找到竞争力相关列")
                return
            
            # 创建子图
            fig, axes = plt.subplots(2, 2, figsize=(15, 10))
            fig.suptitle(title, fontsize=16)
            
            # 竞争力分布直方图
            if 'inquiry_competitive_after' in data.columns:
                axes[0, 0].hist(data['inquiry_competitive_after'], bins=20, alpha=0.7, color='skyblue')
                axes[0, 0].set_title('询价竞争力分布')
                axes[0, 0].set_xlabel('竞争力值')
                axes[0, 0].set_ylabel('频次')
            
            # 价格与竞争力散点图
            if 'finalprice' in data.columns and 'inquiry_competitive_after' in data.columns:
                axes[0, 1].scatter(data['finalprice'], data['inquiry_competitive_after'], alpha=0.6)
                axes[0, 1].set_title('价格与竞争力关系')
                axes[0, 1].set_xlabel('价格 (¥)')
                axes[0, 1].set_ylabel('竞争力')
            
            # 等级竞争力对比
            if 'product_level_name' in data.columns and 'inquiry_competitive_after' in data.columns:
                level_compete = data.groupby('product_level_name')['inquiry_competitive_after'].mean()
                axes[1, 0].bar(range(len(level_compete)), level_compete.values, color='lightcoral')
                axes[1, 0].set_title('各等级平均竞争力')
                axes[1, 0].set_xlabel('产品等级')
                axes[1, 0].set_ylabel('平均竞争力')
                axes[1, 0].set_xticks(range(len(level_compete)))
                axes[1, 0].set_xticklabels(level_compete.index, rotation=45)
            
            # 竞争力趋势（如果有时间数据）
            if 'partition_date' in data.columns and 'inquiry_competitive_after' in data.columns:
                daily_compete = data.groupby('partition_date')['inquiry_competitive_after'].mean()
                axes[1, 1].plot(daily_compete.index, daily_compete.values, marker='o')
                axes[1, 1].set_title('竞争力时间趋势')
                axes[1, 1].set_xlabel('日期')
                axes[1, 1].set_ylabel('平均竞争力')
                axes[1, 1].tick_params(axis='x', rotation=45)
            
            plt.tight_layout()
            st.pyplot(fig)
            
        except Exception as e:
            st.error(f"绘制竞争力分析图失败: {str(e)}")
    
    def display_processing_progress(self, current: int, total: int, message: str = ""):
        """
        显示处理进度
        
        Args:
            current: 当前进度
            total: 总数
            message: 进度消息
        """
        progress = current / total if total > 0 else 0
        
        # 进度条
        progress_bar = st.progress(progress)
        
        # 进度文本
        if message:
            st.text(f"{message} ({current}/{total})")
        else:
            st.text(f"处理进度: {current}/{total} ({progress:.1%})")
        
        return progress_bar
    
    def display_error_message(self, error: Exception, context: str = ""):
        """
        显示错误消息
        
        Args:
            error: 异常对象
            context: 错误上下文
        """
        st.error(f"❌ {context}: {str(error)}")
        
        # 展开显示详细错误信息
        with st.expander("查看详细错误信息"):
            st.code(str(error), language="python")
    
    def display_success_message(self, message: str, details: Optional[Dict[str, Any]] = None):
        """
        显示成功消息
        
        Args:
            message: 成功消息
            details: 详细信息
        """
        st.success(f"✅ {message}")
        
        if details:
            with st.expander("查看详细信息"):
                for key, value in details.items():
                    st.write(f"**{key}**: {value}")
    
    def create_filter_sidebar(self, data: pd.DataFrame) -> Dict[str, Any]:
        """
        创建筛选侧边栏
        
        Args:
            data: 数据框
        
        Returns:
            筛选条件字典
        """
        filters = {}
        
        with st.sidebar:
            st.header("🔍 数据筛选")
            
            # 产品筛选
            if 'product_name' in data.columns:
                products = data['product_name'].unique()
                selected_products = st.multiselect(
                    "选择产品",
                    products,
                    default=products[:5] if len(products) > 5 else products
                )
                filters['products'] = selected_products
            
            # 等级筛选
            if 'product_level_name' in data.columns:
                levels = data['product_level_name'].unique()
                selected_levels = st.multiselect(
                    "选择等级",
                    levels,
                    default=levels
                )
                filters['levels'] = selected_levels
            
            # 价格范围筛选
            if 'finalprice' in data.columns:
                price_range = st.slider(
                    "价格范围",
                    min_value=float(data['finalprice'].min()),
                    max_value=float(data['finalprice'].max()),
                    value=(float(data['finalprice'].min()), float(data['finalprice'].max()))
                )
                filters['price_range'] = price_range
        
        return filters
    
    def apply_filters(self, data: pd.DataFrame, filters: Dict[str, Any]) -> pd.DataFrame:
        """
        应用筛选条件
        
        Args:
            data: 原始数据
            filters: 筛选条件
        
        Returns:
            筛选后的数据
        """
        filtered_data = data.copy()
        
        # 产品筛选
        if 'products' in filters and filters['products']:
            filtered_data = filtered_data[filtered_data['product_name'].isin(filters['products'])]
        
        # 等级筛选
        if 'levels' in filters and filters['levels']:
            filtered_data = filtered_data[filtered_data['product_level_name'].isin(filters['levels'])]
        
        # 价格范围筛选
        if 'price_range' in filters:
            min_price, max_price = filters['price_range']
            filtered_data = filtered_data[
                (filtered_data['finalprice'] >= min_price) & 
                (filtered_data['finalprice'] <= max_price)
            ]
        
        return filtered_data